home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / src_1218.zip / AX25SUBR.C < prev    next >
C/C++ Source or Header  |  1991-04-17  |  6KB  |  244 lines

  1. /* Low level AX.25 routines:
  2.  *  callsign conversion
  3.  *  control block management
  4.  *
  5.  * Copyright 1991 Phil Karn, KA9Q
  6.  */
  7. #include <stdio.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "timer.h"
  11. #include "ax25.h"
  12. #include "lapb.h"
  13. #include <ctype.h>
  14.  
  15. struct ax25_cb *Ax25_cb;
  16.  
  17. /* Default AX.25 parameters */
  18. int32 T3init = 0;        /* No keep-alive polling */
  19. int16 Maxframe = 1;        /* Stop and wait */
  20. int16 N2 = 10;            /* 10 retries */
  21. int16 Axwindow = 2048;        /* 2K incoming text before RNR'ing */
  22. int16 Paclen = 256;        /* 256-byte I fields */
  23. int16 Pthresh = 128;        /* Send polls for packets larger than this */
  24. int32 Axirtt = 5000;        /* Initial round trip estimate, ms */
  25. int16 Axversion = V1;        /* Protocol version */
  26. int32 Blimit = 30;        /* Retransmission backoff limit */
  27.  
  28. /* Look up entry in connection table */
  29. struct ax25_cb *
  30. find_ax25(addr)
  31. register char *addr;
  32. {
  33.     register struct ax25_cb *axp;
  34.     struct ax25_cb *axlast = NULLAX25;
  35.  
  36.     /* Search list */
  37.     for(axp = Ax25_cb; axp != NULLAX25; axlast=axp,axp = axp->next){
  38.         if(addreq(axp->remote,addr)){
  39.             if(axlast != NULLAX25){
  40.                 /* Move entry to top of list to speed
  41.                  * future searches
  42.                  */
  43.                 axlast->next = axp->next;
  44.                 axp->next = Ax25_cb;
  45.                 Ax25_cb = axp;
  46.             }
  47.             return axp;
  48.         }
  49.     }
  50.     return NULLAX25;
  51. }
  52.  
  53. /* Remove entry from connection table */
  54. void
  55. del_ax25(conn)
  56. struct ax25_cb *conn;
  57. {
  58.     register struct ax25_cb *axp;
  59.     struct ax25_cb *axlast = NULLAX25;
  60.  
  61.     for(axp = Ax25_cb; axp != NULLAX25; axlast=axp,axp = axp->next){
  62.         if(axp == conn)
  63.             break;
  64.     }
  65.     if(axp == NULLAX25)
  66.         return;    /* Not found */
  67.  
  68.     /* Remove from list */
  69.     if(axlast != NULLAX25)
  70.         axlast->next = axp->next;
  71.     else
  72.         Ax25_cb = axp->next;
  73.  
  74.     /* Timers should already be stopped, but just in case... */
  75.     stop_timer(&axp->t1);
  76.     stop_timer(&axp->t3);
  77.  
  78.     /* Free allocated resources */
  79.     free_q(&axp->txq);
  80.     free_q(&axp->rxasm);
  81.     free_q(&axp->rxq);
  82.     free((char *)axp);
  83. }
  84.  
  85. /* Create an ax25 control block. Allocate a new structure, if necessary,
  86.  * and fill it with all the defaults. The caller
  87.  * is still responsible for filling in the reply address
  88.  */
  89. struct ax25_cb *
  90. cr_ax25(addr)
  91. char *addr;
  92. {
  93.     register struct ax25_cb *axp;
  94.  
  95.     if(addr == NULLCHAR)
  96.         return NULLAX25;
  97.  
  98.     if((axp = find_ax25(addr)) == NULLAX25){
  99.         /* Not already in table; create an entry
  100.          * and insert it at the head of the chain
  101.          */
  102.         axp = (struct ax25_cb *)callocw(1,sizeof(struct ax25_cb));
  103.         axp->next = Ax25_cb;
  104.         Ax25_cb = axp;
  105.     }
  106.     axp->user = -1;
  107.     axp->state = LAPB_DISCONNECTED;
  108.     axp->maxframe = Maxframe;
  109.     axp->window = Axwindow;
  110.     axp->paclen = Paclen;
  111.     axp->proto = Axversion;    /* Default, can be changed by other end */
  112.     axp->pthresh = Pthresh;
  113.     axp->n2 = N2;
  114.     axp->srt = Axirtt;
  115.     set_timer(&axp->t1,2*axp->srt);
  116.     axp->t1.func = recover;
  117.     axp->t1.arg = axp;
  118.  
  119.     set_timer(&axp->t3,T3init);
  120.     axp->t3.func = pollthem;
  121.     axp->t3.arg = axp;
  122.  
  123.     /* Always to a receive and state upcall as default */
  124.     axp->r_upcall = s_arcall;
  125.     axp->s_upcall = s_ascall;
  126.  
  127.     return axp;
  128. }
  129.  
  130. /*
  131.  * setcall - convert callsign plus substation ID of the form
  132.  * "KA9Q-0" to AX.25 (shifted) address format
  133.  *   Address extension bit is left clear
  134.  *   Return -1 on error, 0 if OK
  135.  */
  136. int
  137. setcall(out,call)
  138. char *out;
  139. char *call;
  140. {
  141.     int csize;
  142.     unsigned ssid;
  143.     register int i;
  144.     register char *dp;
  145.     char c;
  146.  
  147.     if(out == NULLCHAR || call == NULLCHAR || *call == '\0')
  148.         return -1;
  149.  
  150.     /* Find dash, if any, separating callsign from ssid
  151.      * Then compute length of callsign field and make sure
  152.      * it isn't excessive
  153.      */
  154.     dp = strchr(call,'-');
  155.     if(dp == NULLCHAR)
  156.         csize = strlen(call);
  157.     else
  158.         csize = dp - call;
  159.     if(csize > ALEN)
  160.         return -1;
  161.     /* Now find and convert ssid, if any */
  162.     if(dp != NULLCHAR){
  163.         dp++;    /* skip dash */
  164.         ssid = atoi(dp);
  165.         if(ssid > 15)
  166.             return -1;
  167.     } else
  168.         ssid = 0;
  169.     /* Copy upper-case callsign, left shifted one bit */
  170.     for(i=0;i<csize;i++){
  171.         c = *call++;
  172.         if(islower(c))
  173.             c = toupper(c);
  174.         *out++ = c << 1;
  175.     }
  176.     /* Pad with shifted spaces if necessary */
  177.     for(;i<ALEN;i++)
  178.         *out++ = ' ' << 1;
  179.     
  180.     /* Insert substation ID field and set reserved bits */
  181.     *out = 0x60 | (ssid << 1);
  182.     return 0;
  183. }
  184. int
  185. addreq(a,b)
  186. register char *a,*b;
  187. {
  188.     if(memcmp(a,b,ALEN) != 0 || ((a[ALEN] ^ b[ALEN]) & SSID) != 0)
  189.         return 0;
  190.     else
  191.         return 1;
  192. }
  193. /* Convert encoded AX.25 address to printable string */
  194. char *
  195. pax25(e,addr)
  196. char *e;
  197. char *addr;
  198. {
  199.     register int i;
  200.     char c;
  201.     char *cp;
  202.  
  203.     cp = e;
  204.     for(i=ALEN;i != 0;i--){
  205.         c = (*addr++ >> 1) & 0x7f;
  206.         if(c != ' ')
  207.             *cp++ = c;
  208.     }
  209.     if((*addr & SSID) != 0)
  210.         sprintf(cp,"-%d",(*addr >> 1) & 0xf);    /* ssid */
  211.     else
  212.         *cp = '\0';
  213.     return e;
  214. }
  215.  
  216. /* Figure out the frame type from the control field
  217.  * This is done by masking out any sequence numbers and the
  218.  * poll/final bit after determining the general class (I/S/U) of the frame
  219.  */
  220. int16
  221. ftype(control)
  222. register int control;
  223. {
  224.     if((control & 1) == 0)    /* An I-frame is an I-frame... */
  225.         return I;
  226.     if(control & 2)        /* U-frames use all except P/F bit for type */
  227.         return (int16)(uchar(control) & ~PF);
  228.     else            /* S-frames use low order 4 bits for type */
  229.         return (int16)(uchar(control) & 0xf);
  230. }
  231.  
  232. void
  233. lapb_garbage(red)
  234. int red;
  235. {
  236.     register struct ax25_cb *axp;
  237.  
  238.     for(axp=Ax25_cb;axp != NULLAX25;axp = axp->next){
  239.         mbuf_crunch(&axp->rxq);
  240.         mbuf_crunch(&axp->rxasm);
  241.     }
  242. }
  243.  
  244.